﻿using System;
using System.Collections.Generic;
using System.Linq;
using Atmk.WaterMeter.MIS.Commons;
using Atmk.WaterMeter.MIS.Commons.Interfaces;
using Atmk.WaterMeter.MIS.Commons.Interfaces.Logic;
using Atmk.WaterMeter.MIS.Commons.Interfaces.Logic.Statistics;
using Atmk.WaterMeter.MIS.Commons.Interfaces.Repository;
using Atmk.WaterMeter.MIS.Commons.Utils;
using Atmk.WaterMeter.MIS.Datas;
using Atmk.WaterMeter.MIS.Entities;
using Atmk.WaterMeter.MIS.Entities.Enums;
using Atmk.WaterMeter.MIS.Entities.Models;

//TODO：结算部分，后期需要单独优化，用于水费结算，现在仅是简单计算逻辑
namespace Atmk.WaterMeter.MIS.Logic
{
    /// <summary>
    /// 
    /// </summary>
    public class SettlementManageLogic : ISettlementManageLogic
    {
        private static readonly NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();

        private readonly IRepository _repository;
        private readonly IStepTariffRepository _stepTariffRepository;
        private readonly IBaseInfoLogic _baseInfoLogic;
        private readonly IDistrictLogic _districtLogic;


        public SettlementManageLogic(
            IRepository repository,
            IStepTariffRepository stepTariffRepository,
        IBaseInfoLogic baseInfoLogic,
            IDistrictLogic districtLogic
        )
        {
            _repository = repository;
            _stepTariffRepository = stepTariffRepository;
            _baseInfoLogic = baseInfoLogic;
            _districtLogic = districtLogic;
        }
        /// <summary>
        /// 查询结算信息
        /// </summary>
        /// <param name="payloadId"></param>
        /// <param name="aid"></param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <param name="meterType"></param>
        /// <param name="endTime"></param>
        /// <param name="count"></param>
        /// <param name="searchType"></param>
        /// <param name="searchValue"></param>
        /// <param name="startTime"></param>
        /// <returns></returns>
        //public object SelectSettlement(string payloadId, string aid, int page, int pageSize, string meterType,
        //    DateTime startTime, DateTime endTime, out int count, string searchType = "", string searchValue = "")
        //{
        //    try
        //    {
        //        //第一步 获取所有用户信息
        //        var districtlist =
        //            Enumerable.ToList<District>(_repository.FindAll<District>());
        //        //获取主区域及下所有子区域信息
        //        var districts = _districtLogic.GetDistrictsByUid(payloadId, districtlist);
        //        if (!string.IsNullOrEmpty(aid))
        //        {
        //            districts = _districtLogic.DistrictEntitiesById(aid, districtlist);
        //        }

        //        if (districts.Count == 0)
        //            districts = districtlist.Where(d => d.Id.ToString() == aid).ToList();
        //        //获取业主信息
        //        var owners = Enumerable.Where<Owner>(_repository.FindAll<Owner>(), o =>
        //            districts.Select(d => d.Id.ToString()).Contains(o.DistrictId) &&
        //            o.RecordState == (int)RecordStateEnum.Normal).ToList();
        //        //条件筛选
        //        owners = _baseInfoLogic.QuerySearchOwner(searchType, searchValue, owners);
        //        //获取水表信息
        //        var meters = Enumerable.Where<Meter>(_repository.FindAll<Meter>(), m =>
        //                owners.Select(o => o.Id.ToString()).Contains(m.OwnerId) &&
        //                m.RecordState == (int)RecordStateEnum.Normal)
        //            .ToList();
        //        meters = _baseInfoLogic.QuerySearchMeter(searchType, searchValue, meters);

        //        //获取结算信息
        //        var settlements = Enumerable.Where<SettlementRecord>(
        //            _repository.FindAll<SettlementRecord>(), s =>
        //                meters.Select(m => m.MeterNumber).Contains(s.MeterNumber) &&
        //                s.RecordState == (int)RecordStateEnum.Normal).ToList();
        //        count = settlements.Count;
        //        var result = new object[count];
        //        for (var i = 0; i < settlements.Count; i++)
        //        {
        //            var settlement = settlements[i];
        //            var meter = meters.First(m => m.MeterNumber == settlement.MeterNumber);
        //            var owner = owners.First(o => o.Id.ToString() == meter.OwnerId);
        //            var district = districts.First(d => owner.DistrictId.Contains(d.Id.ToString()));
        //            result[i] = new
        //            {
        //                districtId = district.Id, //片区Id
        //                districtName = district.Name, //片区名称
        //                ownerId = owner.Id.ToString(), //业主Id                
        //                ownerName = owner.Name, //业主名称
        //                houseNumber = owner.HouseNumber, //门牌号 
        //                settlementId = settlement.Id.ToString(), //结算记录编号     
        //                settlementTime = settlement.SettlementTime.ToString("yyyy-MM"), //结算月份
        //                priceId = _stepTariffRepository.GetPriceName(meter.PrcieStepId), //水价名称
        //                startRead = settlement.StartRead, //起始读数
        //                endRead = settlement.EndRead, //终止时读数
        //                monthAmount = settlement.MeterValue, //用量
        //                cost = settlement.SettlementMoney, //费用
        //                settlementStatus = settlement.PaymentStatus //结算记录状态  0 可以撤销 1 不可以撤销-已付费
        //            };
        //        }
        //        //获取分页数据
        //        var pageList = PaginatedList<object>.Create(result.ToList(), page, pageSize);
        //        return pageList;
        //    }
        //    catch (Exception e)
        //    {
        //        throw new Exception($"查询账户信息错误{e.Message}");
        //    }
        //}


        /// <summary>
        /// 撤销结算
        /// </summary>
        /// <param name="token"></param>
        /// <param name="userId"></param>
        /// <param name="settlementId"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        //public bool RevertSettlement(string userId, string settlementId, out Exception exception)
        //{
        //    //解析成功--mock
        //    exception = null;
        //    try
        //    {
        //        //获取结算记录,判断是否应撤销结算
        //        var settlements = Enumerable
        //            .Where<SettlementRecord>(_repository.FindAll<SettlementRecord>(),
        //                s => s.Id.ToString() == settlementId && s.PaymentStatus == 0).ToList();
        //        if (settlements.Any())
        //        {
        //            var settlement = settlements.First();
        //            var meterReadids = settlement.MeterReadingIds.Split(',').ToList();
        //            var meterReadingRecords = Enumerable
        //                .Where<MeterReadingRecord>(_repository.FindAll<MeterReadingRecord>(),
        //                    r => meterReadids.Contains(r.Id.ToString())).ToList();
        //            //将记录状态改为撤销
        //            settlement.RecordState = RecordStateEnum.Rescind;
        //            _repository.Update(settlement);
        //            //将扣费记录状态改为撤销扣费--如果有
        //            var payments = Enumerable.Where<AmountChangedDownRecord>(_repository.FindAll<AmountChangedDownRecord>(),
        //                p =>
        //                    p.SettlementId == settlement.Id.ToString() && p.RecordState == RecordStateEnum.Normal &&
        //                    p.AmountChangedDownMode == AmountChangedDownMode.水费扣费).ToList();
        //            if (payments.Any())
        //            {
        //                var payment = payments.First();
        //                payment.RecordState = RecordStateEnum.Rescind;
        //                //账户金额修改
        //                var account = Enumerable.First<Account>(_repository
        //                    .FindAll<Account>(), o => o.Id.ToString() == payment.AccountId);
        //                //实际金额=扣费返还-欠费
        //                if (account.Arrears > payment.PaymentSum)
        //                {
        //                    account.Arrears = account.Arrears - payment.PaymentSum;
        //                }
        //                else
        //                {
        //                    account.Balance += payment.PaymentSum - account.Arrears;
        //                    account.Arrears = 0;
        //                }

        //                _repository.Update(payment);

        //                _repository.Update(account);
        //            }
        //            //将所有包括的读表记录改为未结算
        //            for (var i = 0; i < meterReadingRecords.Count; i++)
        //            {
        //                meterReadingRecords[i].CloseState = CloseState.UnCLose;
        //            }
        //            _repository.Update(meterReadingRecords.ToArray());
        //            return true;
        //        }
        //        exception = new Exception("没有找到能撤销的记录");
        //        return false;
        //    }
        //    catch (Exception e)
        //    {
        //        _logger.Error(e.Message, e);
        //        throw new Exception(e.Message, e);
        //    }
        //}

        /// <summary>
        /// 结算方法
        /// </summary>
        /// <param name="staffId"></param>
        /// <param name="aid"></param>
        /// <param name="month"></param>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        //public bool Settlement(string staffId, string aid, DateTime month, out int message, out Exception exception)
        //{
        //    //解析成功--mock
        //    exception = null;
        //    message = 0;
        //    try
        //    {
        //        using (var context = ContextBuilder.Build())
        //        {
        //            //第一步 获取所有用户信息
        //            //var districtlist = Enumerable.ToList<District>(_repository.FindAll<District>());
        //            //var districtlist = context.Districts.ToList();

        //            //因为只有用户ID 通过用户ID 查询项目ID
        //            string Project_Id = context.Users.Where(m => m.Id.ToString() == staffId).Select(m => m.SiteId).FirstOrDefault();
        //            _logger.Info("结算用户ID："+ staffId);
        //            _logger.Info("结算项目ID：" + Project_Id  +" 注意此ID 是否为空！");

        //            //获取主区域及下所有子区域信息
        //            //var districts = _districtLogic.GetDistrictsByUid(staffId, districtlist);
        //            var districts = context.Districts.Where(m => m.ProjectId == Project_Id).ToList();
        //            //if (!string.IsNullOrEmpty(aid))
        //            //{
        //            //    districts = _districtLogic.DistrictEntitiesById(aid, districtlist);
        //            //}
        //            //if (districts.Count == 0)
        //            //    districts = districtlist.Where(d => d.Id.ToString() == aid).ToList();
        //            //获取业主信息
        //            //var owners = Enumerable.Where<Owner>(_repository.FindAll<Owner>(), o =>
        //            //    districts.Select(d => d.Id.ToString()).Contains(o.DistrictId) &&
        //            //    o.RecordState == RecordStateEnum.Normal).ToList();
        //            var owners = context.Owners.Where(m => districts.Select(mm => mm.Id.ToString()).Contains(m.DistrictId) && m.RecordState == RecordStateEnum.Normal).ToList();

        //            //获取业主下的已开户信息
        //            //var accounts = Enumerable.Where<Account>(_repository.FindAll<Account>(), a =>
        //            //    owners.Select(o => o.Id.ToString()).Contains(a.OwnerId) &&
        //            //    a.RecordState == RecordStateEnum.Normal).ToList();
        //            var accounts = context.Accounts.Where(m => owners.Select(mm => mm.Id.ToString()).Contains(m.OwnerId) && m.RecordState == RecordStateEnum.Normal).ToList();

        //            //有表 且 开户的业主
        //            var Owners_haveMeter = owners.Where(o => accounts.Select(a => a.OwnerId).Contains(o.Id.ToString())).ToList();
        //            //获取已开账户水表信息
        //            var meters = Enumerable.Where<Meter>(_repository.FindAll<Meter>(), m =>
        //                Owners_haveMeter.Select(o => o.Id.ToString()).Contains(m.OwnerId) &&
        //                m.RecordState == (int)RecordStateEnum.Normal).ToList();
        //            //获取当前月份该地区所有未结算过的抄表记录
        //            var meterReadings = Enumerable.Where<MeterReadingRecord>(_repository.FindAll<MeterReadingRecord>(), r => meters.Select(m => m.MeterNumber).Contains(r.Number) && r.ReadTime.Year == month.Year && r.ReadTime.Month == month.Month && r.CloseState == (int)CloseState.UnCLose).ToList();

        //            var meterReadings2 = context.MeterReadingRecord.Where(m => meters.Select(mm=> mm.MeterNumber).Contains(m.Number) && m.ReadTime.Year == month.Year && m.ReadTime.Month == month.Month && m.CloseState == (int)CloseState.UnCLose).ToList();

        //            //按日期排序，获取每个的用户的信息集合-for循环
        //            //按照抄表记录中水表编号进行分组
        //            var groupMr = meterReadings.GroupBy(m => m.Number).ToList();
        //            var settlements = new List<SettlementRecord>();
        //            var payments = new List<AmountChangedDownRecord>();
        //            foreach (var item in groupMr)
        //            {
        //                var groupList = item.OrderByDescending(m => m.ReadTime).ToList();
        //                var meter = meters.First(m => m.MeterNumber == item.Key);
        //                var owner = Owners_haveMeter.First(o => o.Id.ToString() == meter.OwnerId);
        //                var account = accounts.First(a => a.OwnerId == owner.Id.ToString());
        //                var resprice = GetPriceList(meter.MeterType, meter.PrcieStepId);
        //                var price = 0m;
        //                if (resprice.Count > 0)
        //                {
        //                    Decimal.TryParse(resprice[0].ToString(), out price);
        //                }
        //                //结算数据按照立方米计算
        //                //TODO:暂时按照立方米整数--应该根据单位进行换算
        //                var startRead = (int)groupList[groupList.Count - 1].Value;
        //                var endRead = (int)groupList[0].Value;
        //                var value = endRead - startRead;

        //                var settlement = new SettlementRecord
        //                {
        //                    SettlementTime = month,
        //                    MeterNumber = item.Key,
        //                    StartTime = groupList[groupList.Count - 1].ReadTime,
        //                    EndTime = groupList[0].ReadTime,
        //                    StartRead = startRead,
        //                    EndRead = endRead,
        //                    MeterValue = value,
        //                    Price1 = price,
        //                    SettlementMoney = value * price,
        //                    MeterReadingIds = string.Join(",", item.Select(m => m.Id).ToArray())
        //                };
        //                //实际金额=余额-扣费
        //                if (account.Balance > settlement.SettlementMoney)
        //                {
        //                    account.Balance = account.Balance - settlement.SettlementMoney;
        //                }
        //                else
        //                {
        //                    account.Arrears += settlement.SettlementMoney - account.Balance;
        //                    account.Balance = 0;
        //                }
        //                context.SaveChanges();
        //                //_repository.Update(account);

        //                settlements.Add(settlement);
        //                //扣费
        //                var payment = new AmountChangedDownRecord
        //                {
        //                    OwnerId = owner.Id.ToString(),
        //                    MeterNumber = meter.MeterNumber,
        //                    AccountId = account.Id.ToString(),
        //                    StaffId = staffId,
        //                    SettlementId = settlement.Id.ToString(),
        //                    AmountChangedDownMode = AmountChangedDownMode.水费扣费,
        //                    PaymentSum = settlement.SettlementMoney
        //                };
        //                payments.Add(payment);
        //            }
        //            var res = _repository.AddRang(settlements.ToArray());
        //            message = res;
        //            ////添加结算记录
        //            //if (res > 0)
        //            //{
        //            //    _repository.AddRang(payments.ToArray());
        //            //    _repository.Update(accounts.ToArray());
        //            //    message = $"结算完成 共{res}条";
        //            //}
        //            //else
        //            //{
        //            //    message = $"结算完成 共{0}条";
        //            //}
        //            //设为结算完成
        //            for (var i = 0; i < meterReadings.Count; i++)
        //            {
        //                meterReadings[i].CloseState = CloseState.Close;
        //            }
        //            _repository.Update(meterReadings.ToArray());
        //            //进行扣费并添加扣费记录
        //        }
        //        return true;
        //    }
        //    catch (Exception e)
        //    {
        //        exception = new Exception(e.Message, e);
        //        _logger.Error(e);
        //        return false;
        //    }
        //}
        /// <summary>
        /// 获取指定水表类型和价格名称下的价格
        /// </summary>
        /// <param name="meterType"></param>
        /// <param name="priceType"></param>
        /// <returns></returns>
        private List<double> GetPriceList(string meterType, string priceId)
        {
            var result = new List<double>();
            var tryParse = Enum.TryParse(meterType, out MeterType meterTypeEnum);
            //if (!tryParse)
            //{
            //    _logger.Warn("meterType can't Convert MeterType Enum");
            //    return new List<double>();
            //}

            //获取价格分界点信息集合
            var prices = Enumerable.Where<PrcieStep>(_repository.FindAll<PrcieStep>(),
            p => p.MeterType == (int)meterTypeEnum && p.Id.ToString() == priceId).ToList();
            if (prices.Count > 0)
            {
                //获取所有价格费用集合
                var fees = Enumerable.Where<PrcieStepFee>(_repository.FindAll<PrcieStepFee>(),
                    f => f.PiceStepId == prices[0].Id.ToString()).ToList();
                if (fees.Count > 0)
                {
                    var price1 = fees.Sum(f => f.Price1); //单价1
                    var price2 = fees.Sum(f => f.Price2); //单价2
                    var price3 = fees.Sum(f => f.Price3); //单价3
                    result.Add(price1);
                    result.Add(price2);
                    result.Add(price3);
                }
            }
            return result;
        }
    }
}